﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;

namespace Liphofra.Mvvm.Navigation
{
    /// <summary>
    /// An implementation of the <c>INavigationService</c> interface that wraps a <c>PhoneApplicationFrame</c>.
    /// </summary>
    public class FrameNavigationService : INavigationService
    {
        private PhoneApplicationFrame _frame;

        /// <summary>
        /// Initializes a new instance of the <see cref="FrameNavigationService"/> class.
        /// </summary>
        /// <param name="frame">The frame to use to provide navigation functionality.</param>
        public FrameNavigationService(PhoneApplicationFrame frame)
        {
            _frame = frame;

            if (_frame != null)
            {
                _frame.Unloaded += Frame_Unloaded;
            }
        }

        private void Frame_Unloaded(object sender, RoutedEventArgs e)
        {
            _frame.Unloaded -= Frame_Unloaded;
            _frame = null;
        }

        #region INavigationService implementation

        /// <summary>
        /// Gets a value indicating whether backward navigation can be performed.
        /// </summary>
        /// <value>
        /// <c>true</c> if backward navigation is possible; otherwise, <c>false</c>.
        /// </value>
        public bool CanGoBack
        {
            get
            {
                if (_frame != null)
                {
                    return _frame.CanGoBack;
                }

                return false;
            }
        }

        /// <summary>
        /// Gets the back stack of the navigation.
        /// </summary>
        public IEnumerable<JournalEntry> BackStack
        {
            get
            {
                if (_frame != null)
                {
                    return _frame.BackStack;
                }

                return null;
            }
        }

        /// <summary>
        /// Navigates forward to the specified content source.
        /// </summary>
        /// <param name="source">The source to navigate to.</param>
        /// <returns>
        ///   <c>true</c> if navigation was successful; otherwise, <c>false</c>.
        /// </returns>
        public bool Navigate(Uri source)
        {
            if (_frame != null)
            {
                return _frame.Navigate(source);
            }

            return false;
        }

        /// <summary>
        /// Invokes backward navigation of one page.
        /// </summary>
        public void GoBack()
        {
            if (_frame != null)
            {
                _frame.GoBack();
            }
        }

        /// <summary>
        /// Removes the most current back stack entry from the navigation stack.
        /// </summary>
        /// <returns>
        /// The entry that was removed from the navigation stack.
        /// </returns>
        public JournalEntry RemoveBackEntry()
        {
            if (_frame != null)
            {
                return _frame.RemoveBackEntry();
            }

            return null;
        }

        #endregion
    }
}